#include "configure.h"

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>

Configure::Configure(const char *dir, const char *fname, char assign_symbol) : assign_symbol(assign_symbol)
{
    fpath = new char[strlen(dir) + strlen(fname) + 2];
    if (fpath == NULL) {
        fprintf (stderr, "Configure allocate memory failed!\n");
        exit(1);
    }

    sprintf(fpath, "%s/%s", dir, fname);

    fin = fopen(fpath, "r");
    if (fin == NULL) {
        fprintf(stderr, "Opening file [%s] failed!\n", fpath);
        exit(1);
    }
    read_configure();
}

Configure::Configure(const char *fname, char assign_symbol) : assign_symbol(assign_symbol)
{
    fpath = new char[strlen(fname) + 1];
    if (fpath == NULL) {
        fprintf (stderr, "Configure allocate memory failed!\n");
        exit(1);
    }

    sprintf(fpath, "%s", fname);

    fin = fopen(fpath, "r");
    if (fin == NULL) {
        fprintf(stderr, "Opening file [%s] failed!\n", fpath);
        exit(1);
    }
    read_configure();
}

Configure::~Configure()
{
    fclose(fin);
    delete [] fpath;
}

void
Configure::read_configure()
{
    char tmp[1024];
    char *key, *value;
    bool succeed;

    while (fgets(tmp, sizeof(tmp), fin)) {
        succeed = get_key_value(tmp, key, value);
        if (!succeed) continue;
        data_map[key] = value;

        delete [] key;
        delete [] value;
    }
}

bool
Configure::get_key_value(const char *str, char *&key, char *&value)
{
    size_t str_len = strlen(str);

    key = new char[str_len + 1];
    value = new char[str_len + 1];

    if (key == NULL || value == NULL) {
        fprintf (stderr, "Configure allocate memory failed!\n");
        exit(1);
    }
    size_t left, right;

    left = 0, right = str_len - 1;
    while (left < str_len && isspace(str[left])) {
        ++left;
    }
    while (right >= left && isspace(str[right])) {
        --right;
    }

    if (left > right || str[left] == '#') return false;

    size_t key_len, value_len;

    key_len = 0;
    while (left <= right && str[left] != assign_symbol) {
        key[key_len++] = str[left++];
    }
    while (key_len > 0 && isspace(key[key_len - 1])) {
        --key_len;
    }
    key[key_len] = '\0';

    if (left > right) {
        fprintf(stderr, "Wrong data, ignore this line!\n");
        return false;
    }
    for (++left; left <= right && isspace(str[left]); ++left)
        ;

    value_len = 0;
    while (left <= right) {
        value[value_len++] = str[left++];
    }
    value[value_len] = '\0';

    if (key_len == 0 || value_len == 0) {
        fprintf(stderr, "Wrong data, ignore this line!\n");
        return false;
    }
    return true;
}

const char *
Configure::operator[](const char *key)
{
    if (data_map.find(key) == data_map.end()) {
        fprintf(stderr, "Key [%s] not exists!\n", key);
        return NULL;
    }
    return data_map[key].c_str();
}

const char *
Configure::operator[](const string &key)
{
    return operator[](key.c_str());
}
